package name.maunz.client.timechart;


import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.widgetideas.graphics.client.Color;
import com.google.gwt.widgetideas.graphics.client.GWTCanvas;
import com.google.gwt.xml.client.Element;
import com.google.gwt.xml.client.NodeList;

public class TimechartWidget extends Composite implements TimechartInterface {
	protected float OldX, OldY;
	protected boolean firstPoint = true;
	protected int Width = 500, Height = 200;
	protected GWTCanvas Canvas;
	protected HorizontalPanel CanvasPanel, ControlPanel;
	protected VerticalPanel Container;
	protected CheckBox EnableCheck = new CheckBox("Enable");
	protected TextBox XMaxText = new TextBox(), YMinText = new TextBox(),
			YMaxText = new TextBox();
	protected Color BackgroundColor = new Color(0xE8,0xEE,0xF7);
	protected float CoordinateHeight, CoordinateWidth;
	protected double XMin, XMax = Width, YMin, YMax = Height;
	protected double XOffset;
	protected Color StrokeColor = Color.BLUE;
	protected float linewidth = 1, BlankWidth = 10;
	
	protected ClickHandler ApplyClickHandler = new ClickHandler(){
		public void onClick(ClickEvent event) {
			try {
				XMax = Double.valueOf(XMaxText.getText());		
				YMin = Double.valueOf(YMinText.getText());		
				YMax = Double.valueOf(YMaxText.getText());	
				rescale();
			} catch( Exception ex ) {
				YMinText.setText(Double.toString(YMin));
				YMaxText.setText(Double.toString(YMax));
				XMaxText.setText(Double.toString(XMax));
			}			
		}
	};
	
	protected ClickHandler EnableClickHandler = new ClickHandler(){
		public void onClick(ClickEvent event) {
			boolean enable = EnableCheck.getValue();
			CanvasPanel.setVisible(enable);
			if (enable) {
				Canvas.clear();
				autoresize();
				firstPoint = true;				
			}
		}
	};
	
	protected Button ApplyButton = new Button("Apply", ApplyClickHandler);
	
	/**
	 *  resize the canvas to fill its HorizontalPanel.
	 */
	public void autoresize()
	{
		int newwidth = Math.max(CanvasPanel.getOffsetWidth(),200);
		if (newwidth!=Width)
		{
			Width = newwidth;
			Canvas.resize(Width, Height);
			rescale();
		}		
	}

	public void addReference(float yvalue) {
		
	}
	
	public void rescale()
	{
		Canvas.restoreContext();
		Canvas.saveContext();		
		Canvas.clear();
		Canvas.scale(Double.valueOf(Width/(XMax-XMin)).floatValue(), 1);
		Canvas.translate(Double.valueOf(XMin).floatValue(), 0);
		CoordinateHeight = Height;
		CoordinateWidth = Double.valueOf(XMax-XMin).floatValue();
		YMinText.setText(Double.toString(YMin));
		YMaxText.setText(Double.toString(YMax));
		XMaxText.setText(Double.toString(XMax));
		firstPoint = true;
	}
	
	public void setYRange(float min, float max)
	{
		YMin = min;
		YMax = max;
		rescale();
	}
	
	public void setXRange(float min, float max)
	{
		XMin = min;
		XMax = max;
		rescale();
	}
	
	
	public void addPoint(double newx, double newy)
	{
		float y = Double.valueOf(Height*(1-(newy-YMin)/(YMax-YMin))).floatValue();
		float x = Double.valueOf(newx-XOffset).floatValue();
		if (firstPoint) {
			OldX=0; OldY=y; XOffset=newx;
			firstPoint = false;
		} else {
			if (x>CoordinateWidth)
			{
				x = x % CoordinateWidth;
				Canvas.setFillStyle(BackgroundColor);
				float toblank = Math.max(BlankWidth, x>OldX?2*(x-OldX):2*x);
				Canvas.fillRect(OldX, 0, toblank, CoordinateHeight);
			}
			Canvas.beginPath();
			Canvas.setLineWidth(linewidth);
			Canvas.setStrokeStyle(StrokeColor);
			Canvas.moveTo(OldX, OldY);
			if (x<OldX)	{
				OldX= x; OldY = y;
			} else {
				OldX = x; OldY = y;
				Canvas.lineTo(OldX, OldY);
			}
			Canvas.stroke();
		}			
	}
	
	public TimechartWidget()
	{
	}	
	
	public boolean isEnabled() {
		return EnableCheck.getValue();
	}
	
	public void initialize(Element domelement) {
		if (domelement!=null) {
			NodeList Styles = domelement.getElementsByTagName("style");
			if (Styles.getLength()>0)
			{
				Element Style = (Element) Styles.item(0);
				Width = Style.hasAttribute("width")?Integer.parseInt(Style.getAttribute("width")):Width;
				Height = Style.hasAttribute("height")?Integer.parseInt(Style.getAttribute("height")):Height;
				XMax = Style.hasAttribute("xmax")?Double.parseDouble(Style.getAttribute("xmax")):XMax;
				YMin = Style.hasAttribute("ymin")?Double.parseDouble(Style.getAttribute("ymin")):YMin;
				YMax = Style.hasAttribute("ymax")?Double.parseDouble(Style.getAttribute("ymax")):YMax;				
				linewidth = Style.hasAttribute("linewidth")?Float.parseFloat(Style.getAttribute("linewidth")):linewidth;
				StrokeColor = Style.hasAttribute("color")?new Color(Style.getAttribute("color")):StrokeColor;
				BlankWidth = Style.hasAttribute("blankwidth")?Float.parseFloat(Style.getAttribute("blankwidth")):1;
			}
		}
		Canvas = new GWTCanvas(Width,Height);
		CanvasPanel = new HorizontalPanel();
		CanvasPanel.add(Canvas);
		CanvasPanel.setStyleName("Canvas");
		
		ControlPanel = new HorizontalPanel();
		EnableCheck.addClickHandler(EnableClickHandler);
		ControlPanel.add(EnableCheck);
		XMaxText.setText(Double.toString(XMax));
		ControlPanel.add(XMaxText);
		YMinText.setText(Double.toString(YMin));
		ControlPanel.add(YMinText);
		YMaxText.setText(Double.toString(YMax));
		ControlPanel.add(YMaxText);
		ControlPanel.add(ApplyButton);
		
		CanvasPanel.setVisible( EnableCheck.getValue() );
		CanvasPanel.setWidth("100%");
		
		Container = new VerticalPanel();
		Container.setWidth("100%");
		Container.add(ControlPanel);
		Container.add(CanvasPanel);
		initWidget(Container);

		String BackgroundColorString = DOM.getStyleAttribute(CanvasPanel.getElement(),
													"backgroundColor");
		if (BackgroundColorString!=null && !BackgroundColorString.equals("")) 
			BackgroundColor = new Color(BackgroundColorString);
		Canvas.setLineWidth(linewidth);
		Canvas.setStrokeStyle(StrokeColor);
		Canvas.saveContext();
		rescale();
	}
	
	public Widget getWidget() {
		return this;
	}
}
